// 停车信息
interface IEntryInfo {
  number: string; // 车牌号
  inTime: number; // 进入时间
  place?: IParkPlace; // 车位
}

// 车位
class IParkPlace {
  isEmpty = true;
  enter() {
    this.isEmpty = false;
  }
  out() {
    this.isEmpty = true;
  }
}

// 车牌
class ICar {
  number: string;
  constructor(number: string) {
    this.number = number;
  }
}

// 层
class IParkFloor {
  index: number; // 楼层
  parkPlaces: IParkPlace[]; // 车位数
  constructor(index: number, places: IParkPlace[]) {
    this.index = index;
    this.parkPlaces = places;
  }
  // 获取每层空闲车位数量
  get emptyPlaceNum(): number {
    let num = 0;
    for (const place of this.parkPlaces) {
      if (place.isEmpty) num++;
    }
    return num;
  }
}

// 停车场
class IPark {
  parkFloors: IParkFloor[]; // 所有停车位
  entryInfoList: Map<string, IEntryInfo> = new Map();
  constructor(floors: IParkFloor[]) {
    this.parkFloors = floors;
  }
  // 进入
  into(car): IEntryInfo {
    return {
      number: car.number,
      inTime: Date.now(),
      // place: undefined as undefined | IParkPlace,
    };
  }
  // 离开
  leave(info) {
    const { number, inTime } = info;
    const duration = Date.now() - inTime; // 停车时长
    console.log(`车牌号 ${number}，停车时长 ${duration} `);
  }
  // 停车
  getInto(car: ICar) {
    const entryInfo = this.into(car);
    const randomFloor = Math.floor(Math.random() * 3) + 1;
    const randomParking = Math.floor(Math.random() * 10) + 1; // 某个车位
    const place = this.parkFloors[randomFloor].parkPlaces[randomParking]; // 停在第一层的某个车位
    place.enter(); // 进入车位
    entryInfo.place = place; // 记录停车信息
    this.entryInfoList.set(car.number, entryInfo); // key value
  }
  // 取车
  out(car: ICar) {
    const entryInfo = this.entryInfoList.get(car.number); // 获取停车信息
    if (entryInfo == null) return;
    const { place } = entryInfo;
    if (place == null) return;
    place.out(); // 从车位离开
    this.leave(entryInfo);
    this.entryInfoList.delete(car.number);
  }
  get emptyInfo(): string {
    return this.parkFloors
      .map((floor) => {
        return `${floor.index} 层还有 ${floor.emptyPlaceNum} 个空闲车位`;
      })
      .join("\n");
  }
}

const floors: IParkFloor[] = [];
for (let i = 0; i < 3; i++) {
  const places: IParkPlace[] = [];
  for (let i = 0; i < 10; i++) {
    places[i] = new IParkPlace();
  }
  floors.push(new IParkFloor(i + 1, places));
}

const park = new IPark(floors);
const car1 = new ICar("A1");
park.getInto(car1);
console.log(park);
console.log(park.emptyInfo);
setTimeout(() => {
  park.out(car1);
  console.log(park);
  console.log(park.emptyInfo);
}, 10000);
